package com.treasure.mall.biz.service.core.integral.impl;

import com.treasure.mall.biz.base.AbstractSearchableCrudService;
import com.treasure.mall.biz.base.SpecificationAndSort;
import com.treasure.mall.biz.dto.BaseSaveDTO;
import com.treasure.mall.biz.dto.BaseSearchDTO;
import com.treasure.mall.biz.dto.condition.CommonCondition;
import com.treasure.mall.biz.dto.integral.ProductSaveDTO;
import com.treasure.mall.biz.entity.integral.IntegralProductPO;
import com.treasure.mall.biz.entity.integral.IntegralProductPO_;
import com.treasure.mall.biz.repository.integral.IntegralProductRepository;
import com.treasure.mall.biz.service.core.integral.IntegralProductService;
import com.treasure.mall.zbq.common.base.ApiResult;
import com.treasure.mall.zbq.common.exception.ApiException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;

/**
 * @author allan
 * @version 1.0.0
 * @date 2020/8/22
 */
@Service
public class IntegralProductServiceImpl extends AbstractSearchableCrudService<IntegralProductPO, Long> implements IntegralProductService {
    private IntegralProductRepository productRepository;

    @Autowired
    protected IntegralProductServiceImpl(IntegralProductRepository repository) {
        super(repository);
        this.productRepository = repository;
    }

    @Override
    protected SpecificationAndSort<IntegralProductPO> specificationAndSort(BaseSearchDTO searchDTO) {
        CommonCondition condition = (CommonCondition) searchDTO;

        Specification<IntegralProductPO> specification = (root, query, cb) -> {
            List<Predicate> predicates = new ArrayList<>();

            predicates.add(cb.equal(root.get(IntegralProductPO_.deleted), false));

            if (!StringUtils.isEmpty(condition.getKeyword())) {
                predicates.add(cb.like(root.get(IntegralProductPO_.title), likeAll(condition.getKeyword())));
            }

            return cb.and(predicates.toArray(new Predicate[predicates.size()]));
        };

        Sort sort = new Sort(Sort.Direction.DESC, "createTime");

        return new SpecificationAndSort<>(specification, sort);
    }

    @Override
    public IntegralProductPO save(BaseSaveDTO saveDTO) {
        ProductSaveDTO dto = (ProductSaveDTO) saveDTO;

        IntegralProductPO po;
        if (dto.getId() > 0) {
            po = findById(dto.getId());
        } else {
            po = new IntegralProductPO();
            po.setPublished(dto.isPublished());
            po.setStore(dto.getStore());
        }
        po.setTitle(dto.getTitle());
        po.setSubTitle(dto.getSubTitle());
        po.setPropMaterial(dto.getPropMaterial());
        po.setPropSize(dto.getPropSize());
        po.setLocation(dto.getLocation());
        po.setWeightUnit(dto.getWeightUnit());
        po.setWeight(dto.getWeight());
        po.setPrice(dto.getPrice());
        po.setIntegral(dto.getIntegral());
        po.setLimitExchange(dto.getLimitExchange());
        po.setImages(dto.getImages());
        po.setThumbnail(po.imageArray()[0]);
        po.setDesc(dto.getDesc());

        return save(po);
    }

    @Override
    @Transactional
    public void minusStore(Long productId, int num) {
        while (true) {
            IntegralProductPO productPO = findById(productId);
            if (productPO.getStore() < num) {
                //库存不足
                throw new ApiException(ApiResult.error("商品库存不足"));
            }
            int index = productRepository.minusStore(productPO.getId(), num, productPO.getVersion());
            if (index > 0) {
                break;
            }
        }
    }

    @Override
    @Transactional
    public void addStore(Long productId, int num) {
        IntegralProductPO po = findById(productId);
        po.setStore(po.getStore() + num);

        save(po);
    }

    @Override
    public void publishedToggle(Long productId) {
        IntegralProductPO po = findById(productId);
        if (po.isPublished()) {
            po.setPublished(false);
        } else {
            po.setPublished(true);
        }
        save(po);
    }
}
